package com.siyu.common.utils;

import cn.hutool.poi.word.WordUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.List;

public class WordReport {

    private XWPFDocument document;

    private XWPFRun xwpfRun;

    public static String defaultFontFamily = "宋体";

    public WordReport() {
        this.document = new XWPFDocument();
    }

    /**
     * 添加一个头标题
     *
     * @param text       文本内容
     * @param fontFamily 字体
     * @param FontSize   字体大小
     * @param bold       是否加粗
     */
    public WordReport setTitle(String text, String fontFamily, int FontSize, boolean bold) {
        XWPFParagraph titleParagraph = document.createParagraph();
        titleParagraph.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleParagraphRun = titleParagraph.createRun();
        titleParagraphRun.setText(text);
        titleParagraphRun.setFontFamily(fontFamily);
        titleParagraphRun.setFontSize(FontSize);
        titleParagraphRun.setFontSize(FontSize);
        titleParagraphRun.setBold(bold);
        titleParagraphRun.setColor("FF0000");
        xwpfRun = titleParagraphRun;
        return this;
    }
    public WordReport setTitle(String text, String fontFamily, int FontSize, boolean bold,String color) {
        XWPFParagraph titleParagraph = document.createParagraph();
        titleParagraph.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleParagraphRun = titleParagraph.createRun();
        titleParagraphRun.setText(text);
        titleParagraphRun.setFontFamily(fontFamily);
        titleParagraphRun.setFontSize(FontSize);
        titleParagraphRun.setFontSize(FontSize);
        titleParagraphRun.setBold(bold);
        titleParagraphRun.setColor(color);
        xwpfRun = titleParagraphRun;
        return this;
    }

    public WordReport nextLine() {
        xwpfRun.addCarriageReturn();
        return this;
    }

    public void write(OutputStream outputStream) throws IOException {
        document.write(outputStream);
    }

    /**
     * 画一条线
     *
     * @param color
     * @return
     */

    public WordReport drawLine(String color) {
        XWPFParagraph p1 = document.createParagraph();
        p1.setBorderBottom(Borders.SINGLE);
        setBorderBottomColor(p1, color);
        xwpfRun = p1.createRun();
        return this;
    }

    private void setBorderBottomColor(XWPFParagraph paragraph, String rgb) {
        if (paragraph.getCTP().getPPr() == null) return; // no paragraph properties = no borders
        if (paragraph.getCTP().getPPr().getPBdr() == null) return; // no paragraph border
        if (paragraph.getCTP().getPPr().getPBdr().getBottom() == null) return; // no left border
        paragraph.getCTP().getPPr().getPBdr().getBottom().setColor(rgb);
        paragraph.getCTP().getPPr().getPBdr().getBottom().setSz(new BigInteger("20"));
    }

    /**
     * 添加段落
     * @param paragraphAlignment 对齐方式
     * @param text 文本内容
     * @param fontFamily 字体
     * @param FontSize 字体大小
     * @param spacingBefore 行间距
     * @return
     */
    public WordReport addText(ParagraphAlignment paragraphAlignment, String text, String fontFamily, int FontSize, int spacingBefore) {
        return addText(paragraphAlignment, text, fontFamily, FontSize, false, null, spacingBefore);
    }

    public WordReport addText(ParagraphAlignment paragraphAlignment, String text, String fontFamily, int FontSize, boolean bold) {
        return addText(paragraphAlignment, text, fontFamily, FontSize, bold, null, 100);
    }

    public WordReport addText(String text, int FontSize) {
        return addText(ParagraphAlignment.LEFT, text, defaultFontFamily, FontSize, false, null, 100);
    }
    public WordReport addText(String text, int FontSize,boolean bold) {
        return addText(ParagraphAlignment.LEFT, text, defaultFontFamily, FontSize, bold, null, 100);
    }

    public WordReport addText(ParagraphAlignment paragraphAlignment, String text, String fontFamily, int FontSize, boolean bold, String color, int spacingBefore) {
        XWPFParagraph xwpfParagraph = document.createParagraph();
        xwpfParagraph.setAlignment(paragraphAlignment);
        XWPFRun titleParagraphRun = xwpfParagraph.createRun();
        titleParagraphRun.setText(text);
        titleParagraphRun.setFontFamily(fontFamily);
        titleParagraphRun.setFontSize(FontSize);
        titleParagraphRun.setBold(bold);
        if (StringUtils.isNotBlank(color)) {
            titleParagraphRun.setColor(color);
        }
        xwpfParagraph.setSpacingBefore(spacingBefore);
        xwpfParagraph.setSpacingAfter(20);
        xwpfRun = titleParagraphRun;
        return this;
    }


    public WordReport insertImage(File file) throws IOException, InvalidFormatException {
        return insertImage(null,file);
    }

    /**
     * 插入一张图片
     *
     * @param file 本地文件
     * @return
     */
    public WordReport insertImage(String title, File file) throws IOException, InvalidFormatException {
        XWPFParagraph xwpfParagraph = document.createParagraph();
        XWPFRun run = xwpfParagraph.createRun();
        if(StringUtils.isNotBlank(title)){
            run.setText(title);
            run.setBold(true);
        }
        xwpfParagraph.setAlignment(ParagraphAlignment.CENTER);
        FileInputStream is = new FileInputStream(file);
        run.addBreak();
        run.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, file.getName(), Units.toEMU(400), Units.toEMU(200)); // 200x200 pixels
        is.close();
        xwpfRun = run;
        return this;
    }

    //添加柱状图
    public WordReport addBarGraph(String title, String[] series, String[] categories, List<Number[]> values) throws IOException, InvalidFormatException {
        XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);
        // 3、图表相关设置
        chart.setTitleText(title); // 图表标题
        chart.setTitleOverlay(false); // 图例是否覆盖标题

        // 4、图例设置
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(org.apache.poi.xddf.usermodel.chart.LegendPosition.TOP); // 图例位置:上下左右

        // 5、X轴(分类轴)相关设置
        XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); // 创建X轴,并且指定位置
        xAxis.setTitle("时间"); // x轴标题
        String[] xAxisData = categories;
        XDDFCategoryDataSource xAxisSource
                = XDDFDataSourcesFactory.fromArray(xAxisData, chart.formatRange(new CellRangeAddress(0, 0, 0, categories.length - 1))); // 设置X轴数据
        // 6、Y轴(值轴)相关设置
        XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT); // 创建Y轴,指定位置
        // 7、创建折线图对象
        XDDFBarChartData barChartData = (XDDFBarChartData) chart.createData(ChartTypes.BAR, xAxis, yAxis);
        for (int i = 0; i < values.size(); i++) {
            XDDFNumericalDataSource<Number> yAxisSource = XDDFDataSourcesFactory.fromArray(values.get(i), chart.formatRange(new CellRangeAddress(i + 1, i + 1, 0, values.get(i).length - 1))); // 设置Y轴数据
            // 8、加载折线图数据集
            //CellReference cellReference = chart.setSheetTitle(series[i], i);
            XDDFBarChartData.Series lineSeries = (XDDFBarChartData.Series) barChartData.addSeries(xAxisSource, yAxisSource);
            lineSeries.setTitle(series[i], new CellReference(i + 1, i)); // 图例标题
//            lineSeries.setSmooth(true); // 线条样式:true平滑曲线,false折线
//            lineSeries.setMarkerSize((short) 5); // 标记点大小
//            lineSeries.setMarkerStyle(MarkerStyle.CIRCLE); // 标记点样式
        }
        // 9、绘制折线图
        chart.plot(barChartData);
        return this;
    }


    /**
     * 添加chart图
     * @param title 标题
     * @param series 图例
     * @param categories x轴
     * @param values y轴数据
     * @return
     * @throws IOException
     * @throws InvalidFormatException
     */
    public WordReport addChart(String title, String[] series, String[] categories, List<Number[]> values) throws IOException, InvalidFormatException {
        XWPFChart chart = document.createChart(15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER);
        // 3、图表相关设置
        chart.setTitleText(title); // 图表标题
        chart.setTitleOverlay(false); // 图例是否覆盖标题

        // 4、图例设置
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(org.apache.poi.xddf.usermodel.chart.LegendPosition.TOP); // 图例位置:上下左右

        // 5、X轴(分类轴)相关设置
        XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); // 创建X轴,并且指定位置
        xAxis.setTitle("时间"); // x轴标题
        String[] xAxisData = categories;
        XDDFCategoryDataSource xAxisSource
                = XDDFDataSourcesFactory.fromArray(xAxisData, chart.formatRange(new CellRangeAddress(0, 0, 0, categories.length - 1))); // 设置X轴数据
        // 6、Y轴(值轴)相关设置
        XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT); // 创建Y轴,指定位置
        // 7、创建折线图对象
        XDDFLineChartData lineChart = (XDDFLineChartData) chart.createData(ChartTypes.LINE, xAxis, yAxis);
        for (int i = 0; i < values.size(); i++) {
            XDDFNumericalDataSource<Number> yAxisSource = XDDFDataSourcesFactory.fromArray(values.get(i), chart.formatRange(new CellRangeAddress(i + 1, i + 1, 0, values.get(i).length - 1))); // 设置Y轴数据
            // 8、加载折线图数据集
            //CellReference cellReference = chart.setSheetTitle(series[i], i);
            XDDFLineChartData.Series lineSeries = (XDDFLineChartData.Series) lineChart.addSeries(xAxisSource, yAxisSource);
            lineSeries.setTitle(series[i], new CellReference(i + 1, i)); // 图例标题
            lineSeries.setSmooth(true); // 线条样式:true平滑曲线,false折线
            lineSeries.setMarkerSize((short) 5); // 标记点大小
            lineSeries.setMarkerStyle(MarkerStyle.CIRCLE); // 标记点样式
        }
        // 9、绘制折线图
        chart.plot(lineChart);
        return this;
    }

    public WordReport addTable(List<List<String>> data,List<String> head){
        XWPFTable xTable = document.createTable(1,head.size());
        for (int i = 0; i < head.size(); i++) {
            setCellText(xTable.getRow(0).getCell(i), head.get(i), getCellWidth(head.get(i)), "宋体", 10, true);
        }
        for (int i = 0; i < data.size(); i++) {
            XWPFTableRow row = xTable.insertNewTableRow(i + 1);
            row.setHeight(200);
            for (int i1 = 0; i1 < data.get(i).size(); i1++) {
                XWPFTableCell cell = row.createCell();
                try{
                    setCellText(cell, data.get(i).get(i1), getCellWidth(head.get(i1)), "宋体", 10, true);
                }catch (IndexOutOfBoundsException indexOutOfBoundsException){
                    indexOutOfBoundsException.printStackTrace();
                }
            }
        }
        return this;
    }


    private static int getCellWidth(String key) {  //根据不同的列设置列宽
        int cwidth = 2000;
        if ("NO".equals(key)) {
            cwidth = 800;
        }return cwidth;
    }

    public static XWPFRun setTableCellStyle(XWPFTableCell cell, ParagraphAlignment paragraphAlignment, String fontFamily, int fontSize, boolean bold) {
        XWPFParagraph paragraph = cell.getParagraphs().get(0);
        paragraph.setAlignment(paragraphAlignment);
        XWPFRun run = paragraph.createRun();
        run.setFontFamily(fontFamily);
        run.setFontSize(fontSize);
        run.setBold(bold);
        return run;
    }

    public static void setCellText(XWPFTableCell cell, String text, int width, String fontFamily, int fontSize, boolean bold) {
        XWPFParagraph paragraph = cell.getParagraphs().get(0);
        XWPFRun run = paragraph.createRun();
        run.setFontFamily(fontFamily);
        run.setFontSize(fontSize);
        run.setBold(bold);
        run.setText(text);
        CTTc cttc = cell.getCTTc();
        CTTcPr cellPr = cttc.addNewTcPr();
        cellPr.addNewTcW().setW(BigInteger.valueOf(width));
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        CTTcPr ctPr = cttc.addNewTcPr();
        ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
        cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
    }

}
